/**
 * LookupServiceRegistryTest.java
 */

package fss.common;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


import fss.core.config.FssConfigFactory;
import fss.core.config.ServiceRegistryConfig;
import fss.remote.ServiceRegistry;
import fss.remote.util.RemoteFileService;
import fss.transfer.Transfer;
import fss.transfer.TransferId;
import fss.util.rmi.RmiId;
import fss.util.rmi.RmiUtils;

/**
 * A test class to test the logic for finding the most efficient service registry.
 * 
 * @author thinh
 *
 */
public class LookupServiceRegistryTest {
    public static Map<RmiId, Set<RmiId>> getAllServiceRegistry() {
        ServiceRegistryConfig config = FssConfigFactory.getInstance().getRegistryServerConfig();
        List<Integer> portList = config.getPortList();
        List<String> hostList = config.getHostList();
        Map<RmiId, Set<RmiId>> all = new HashMap<RmiId, Set<RmiId>>();
        
        for (String host : hostList) {
            for (int port : portList) {
                try {
                    Registry registry = LocateRegistry.getRegistry(host, port);
                    for(String name : registry.list()) {
                        RmiId _id = new RmiId(host, name, port);
                        Remote remoteObject = RmiUtils.getRemoteObject(_id);
                        if(remoteObject instanceof ServiceRegistry) {
                            ServiceRegistry serviceReg = (ServiceRegistry) remoteObject;
                            try {
                                all.put(serviceReg.getId(), serviceReg.getRegisteredServiceList());
                            } catch(RemoteException e) {
                                // ignore
                            }
                        }
                    }
                } catch (RemoteException e) {
                    // ignore, no service registry at host/port
                }
            }
        }
        return all;
    }
    /**
     * Return the id of an available Service Registry.
     * <p>
     * The logic will pick the registry with the least number of registered services.
     * @return the id.
     */
    public static RmiId lookup() {
        RmiId bestId = null;
        Map<RmiId, Set<RmiId>>  registrationMap = getAllServiceRegistry();
        int min = Integer.MAX_VALUE;
        for(RmiId _id : registrationMap.keySet()) {
            Set<RmiId> registration = registrationMap.get(_id);
            // registration has the least number of connected service(s)
            if(registration.size() < min) {
                bestId = _id;
                min = registration.size();
            } 
            // compare the activities of the connected service(s) 
            else if(registration.size() == min) {
                // find out the total number of activities for all connected services for current
                int totalActivities = 0;
                for(RmiId info : registration) {
                    try {
                        totalActivities += ((RemoteFileService)RmiUtils.getRemoteObject(info)).getStatus().size();
                    } catch (RemoteException e) {
                        // ignore
                    }
                }
                
                // find out the total number of activities for all connected services for the already set min
                int minTotalActivities = 0;
                for(RmiId info : registrationMap.get(bestId)) {
                    try {
                        minTotalActivities += ((RemoteFileService)RmiUtils.getRemoteObject(info)).getStatus().size();
                    } catch (RemoteException e) {
                        // ignore
                    }
                }
                
                if(totalActivities < minTotalActivities) {
                    bestId = _id;
                    min = registration.size();
                }
            }
        }
        return bestId;
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        RmiId id = lookup();
        System.out.println("The best available Service Registry is " + id);
        ServiceRegistry serviceRegistry = (ServiceRegistry) RmiUtils.getRemoteObject(id);
        try {
            Set<RmiId> registration = serviceRegistry.getRegisteredServiceList();
            System.out.println("-- Registration List --");
            for(RmiId info : registration) {
                Map<TransferId, Transfer> serviceActivity = ((RemoteFileService)RmiUtils.getRemoteObject(info)).getStatus();
                System.out.println("" + info + ": number of activities: " + serviceActivity.size());
                
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

}
